const { Op, Sequelize } = require('sequelize');
const { sequelize, User, PointsTransaction } = require('../models');

class PointsService {
  // 添加积分
  static async addPoints(userId, amount, source, description, metadata = {}) {
    const transaction = await sequelize.transaction();
    
    try {
      // 验证参数
      if (!userId || amount <= 0) {
        throw new Error('无效的参数');
      }

      const user = await User.findByPk(userId, { transaction });
      if (!user) {
        throw new Error('用户不存在');
      }
      
      const balanceBefore = parseFloat(user.points) || 0;
      const balanceAfter = balanceBefore + parseFloat(amount);
      
      // 更新用户积分
      await user.update({ points: balanceAfter }, { transaction });
      
      // 记录积分交易
      const pointsTransaction = await PointsTransaction.create({
        userId,
        type: 'earn',
        amount: parseFloat(amount),
        balanceBefore,
        balanceAfter,
        source,
        description,
        relatedId: metadata.orderId || null,
        relatedUserId: metadata.relatedUserId || null
      }, { transaction });
      
      await transaction.commit();
      
      console.log(`用户 ${userId} 获得积分: +${amount}, 余额: ${balanceBefore} -> ${balanceAfter}, 来源: ${source}`);
      
      return { success: true, newBalance: balanceAfter, transaction: pointsTransaction };
    } catch (error) {
      await transaction.rollback();
      console.error(`添加积分失败: 用户${userId}, 金额${amount}, 错误:`, error.message);
      throw error;
    }
  }
  
  // 扣除积分
  static async deductPoints(userId, amount, source, description, metadata = {}) {
    const transaction = await sequelize.transaction();
    
    try {
      // 验证参数
      if (!userId || amount <= 0) {
        throw new Error('无效的参数');
      }

      const user = await User.findByPk(userId, { transaction });
      if (!user) {
        throw new Error('用户不存在');
      }
      
      const balanceBefore = parseFloat(user.points) || 0;
      const deductAmount = parseFloat(amount);
      
      if (balanceBefore < deductAmount) {
        throw new Error(`积分不足，当前余额: ${balanceBefore}, 需要: ${deductAmount}`);
      }
      
      const balanceAfter = balanceBefore - deductAmount;
      
      // 更新用户积分
      await user.update({ points: balanceAfter }, { transaction });
      
      // 记录积分交易
      const pointsTransaction = await PointsTransaction.create({
        userId,
        type: 'consume',
        amount: -deductAmount,
        balanceBefore,
        balanceAfter,
        source: source || 'consume',
        description,
        relatedId: metadata.orderId || null,
        relatedUserId: metadata.relatedUserId || null
      }, { transaction });
      
      await transaction.commit();
      
      console.log(`用户 ${userId} 消费积分: -${amount}, 余额: ${balanceBefore} -> ${balanceAfter}, 来源: ${source}`);
      
      return { success: true, newBalance: balanceAfter, transaction: pointsTransaction };
    } catch (error) {
      await transaction.rollback();
      console.error(`扣除积分失败: 用户${userId}, 金额${amount}, 错误:`, error.message);
      throw error;
    }
  }
  
  // 管理员调整积分
  static async adjustPoints(userId, amount, adminUserId, description, metadata = {}) {
    const transaction = await sequelize.transaction();
    
    try {
      const user = await User.findByPk(userId, { transaction });
      if (!user) {
        throw new Error('用户不存在');
      }
      
      const balanceBefore = parseFloat(user.points) || 0;
      const adjustAmount = parseFloat(amount);
      const balanceAfter = Math.max(0, balanceBefore + adjustAmount);
      
      // 更新用户积分
      await user.update({ points: balanceAfter }, { transaction });
      
      // 记录积分交易
      const pointsTransaction = await PointsTransaction.create({
        userId,
        type: adjustAmount > 0 ? 'earn' : 'consume',
        amount: adjustAmount,
        balanceBefore,
        balanceAfter,
        source: 'admin_adjust',
        description,
        relatedUserId: adminUserId
      }, { transaction });
      
      await transaction.commit();
      
      console.log(`管理员 ${adminUserId} 调整用户 ${userId} 积分: ${adjustAmount > 0 ? '+' : ''}${adjustAmount}, 余额: ${balanceBefore} -> ${balanceAfter}`);
      
      return { success: true, newBalance: balanceAfter, transaction: pointsTransaction };
    } catch (error) {
      await transaction.rollback();
      console.error(`管理员调整积分失败: 用户${userId}, 金额${amount}, 错误:`, error.message);
      throw error;
    }
  }

  // 积分转账（用户之间转账）
  static async transferPoints(fromUserId, toUserId, amount, description = '积分转账') {
    const transaction = await sequelize.transaction();
    
    try {
      // 验证参数
      if (!fromUserId || !toUserId || amount <= 0) {
        throw new Error('无效的参数');
      }

      if (fromUserId === toUserId) {
        throw new Error('不能向自己转账');
      }

      const [fromUser, toUser] = await Promise.all([
        User.findByPk(fromUserId, { transaction }),
        User.findByPk(toUserId, { transaction })
      ]);

      if (!fromUser || !toUser) {
        throw new Error('用户不存在');
      }

      const transferAmount = parseFloat(amount);
      const fromBalanceBefore = parseFloat(fromUser.points) || 0;
      const toBalanceBefore = parseFloat(toUser.points) || 0;

      if (fromBalanceBefore < transferAmount) {
        throw new Error(`积分不足，当前余额: ${fromBalanceBefore}, 需要: ${transferAmount}`);
      }

      const fromBalanceAfter = fromBalanceBefore - transferAmount;
      const toBalanceAfter = toBalanceBefore + transferAmount;

      // 更新两个用户的积分
      await Promise.all([
        fromUser.update({ points: fromBalanceAfter }, { transaction }),
        toUser.update({ points: toBalanceAfter }, { transaction })
      ]);

      // 记录转出交易
      const transferOutTransaction = await PointsTransaction.create({
        userId: fromUserId,
        type: 'consume',
        amount: -transferAmount,
        balanceBefore: fromBalanceBefore,
        balanceAfter: fromBalanceAfter,
        source: 'transfer_out',
        description: `${description} - 转给用户${toUserId}`,
        relatedUserId: toUserId
      }, { transaction });

      // 记录转入交易
      const transferInTransaction = await PointsTransaction.create({
        userId: toUserId,
        type: 'earn',
        amount: transferAmount,
        balanceBefore: toBalanceBefore,
        balanceAfter: toBalanceAfter,
        source: 'transfer_in',
        description: `${description} - 来自用户${fromUserId}`,
        relatedUserId: fromUserId
      }, { transaction });

      await transaction.commit();

      console.log(`积分转账: 用户${fromUserId} -> 用户${toUserId}, 金额: ${transferAmount}`);

      return {
        success: true,
        fromUser: { newBalance: fromBalanceAfter },
        toUser: { newBalance: toBalanceAfter },
        transactions: [transferOutTransaction, transferInTransaction]
      };
    } catch (error) {
      await transaction.rollback();
      console.error(`积分转账失败: ${fromUserId} -> ${toUserId}, 金额${amount}, 错误:`, error.message);
      throw error;
    }
  }
  
  // 每日签到奖励
  static async dailyCheckin(userId) {
    try {
      const user = await User.findByPk(userId);
      if (!user) {
        throw new Error('用户不存在');
      }
      
      const today = new Date();
      today.setHours(0, 0, 0, 0);
      
      // 检查今天是否已经签到
      let todayTransaction;
      try {
        todayTransaction = await PointsTransaction.findOne({
          where: {
            userId,
            source: 'activity',
            description: { [Op.like]: '%签到%' },
            created_at: { [Op.gte]: today }
          }
        });
      } catch (error) {
        // 如果 createdAt 字段不存在，查询最近的签到记录
        todayTransaction = await PointsTransaction.findOne({
          where: {
            userId,
            source: 'activity',
            description: { [Op.like]: '%签到%' }
          },
          order: [['id', 'DESC']]
        });
        
        // 检查是否是今天的记录（通过ID或其他方式）
        if (todayTransaction) {
          const recordDate = new Date(todayTransaction.id * 1000); // 假设ID包含时间信息
          if (recordDate < today) {
            todayTransaction = null;
          }
        }
      }
      
      if (todayTransaction) {
        throw new Error('今天已经签到过了');
      }
      
      // 计算连续签到天数
      const yesterday = new Date(today);
      yesterday.setDate(yesterday.getDate() - 1);
      
      let yesterdayTransaction;
      try {
        yesterdayTransaction = await PointsTransaction.findOne({
          where: {
            userId,
            source: 'activity',
            description: { [Op.like]: '%签到%' },
            created_at: { 
              [Op.gte]: yesterday, 
              [Op.lt]: today 
            }
          }
        });
      } catch (error) {
        // 如果 createdAt 字段不存在，暂时设为 null
        yesterdayTransaction = null;
      }
      
      // 计算连续签到天数
      let consecutiveDays = 1;
      if (yesterdayTransaction) {
        // 从描述中提取连续天数，如果没有则默认为1
        const match = yesterdayTransaction.description.match(/连续(\d+)天/);
        const previousDays = match ? parseInt(match[1]) : 1;
        consecutiveDays = previousDays + 1;
      }
      
      // 计算奖励积分（基础5分，连续签到有额外奖励）
      let rewardPoints = 5;
      if (consecutiveDays >= 7) {
        rewardPoints += 10; // 连续7天额外10分
      } else if (consecutiveDays >= 3) {
        rewardPoints += 5; // 连续3天额外5分
      }
      
      const result = await this.addPoints(
        userId,
        rewardPoints,
        'activity',
        `每日签到奖励（连续${consecutiveDays}天）`
      );
      
      return {
        ...result,
        consecutiveDays,
        rewardPoints
      };
    } catch (error) {
      throw error;
    }
  }
  
  // 邀请奖励
  static async inviteReward(inviterId, inviteeId) {
    try {
      const [inviter, invitee] = await Promise.all([
        User.findByPk(inviterId),
        User.findByPk(inviteeId)
      ]);
      
      if (!inviter || !invitee) {
        throw new Error('用户不存在');
      }
      
      // 给邀请者奖励50积分
      const inviterResult = await this.addPoints(
        inviterId,
        50,
        'invite_register',
        `邀请用户 ${invitee.nickname || invitee.phone} 注册奖励`
      );
      
      // 给被邀请者奖励20积分
      const inviteeResult = await this.addPoints(
        inviteeId,
        20,
        'invite_register',
        `被用户 ${inviter.nickname || inviter.phone} 邀请注册奖励`
      );
      
      return {
        inviterResult,
        inviteeResult
      };
    } catch (error) {
      throw error;
    }
  }
  
  // 获取积分交易记录
  static async getTransactions(userId, options = {}) {
    const {
      type,
      source,
      page = 1,
      limit = 20,
      startDate,
      endDate
    } = options;
    
    const where = { userId };
    
    if (type) {
      where.type = type;
    }
    
    if (source) {
      where.source = source;
    }
    
    // 只有在 created_at 字段存在时才添加时间过滤
    if (startDate || endDate) {
      try {
        where.created_at = {};
        if (startDate) {
          where.created_at[Op.gte] = new Date(startDate);
        }
        if (endDate) {
          where.created_at[Op.lte] = new Date(endDate);
        }
      } catch (error) {
        // 如果 created_at 字段不存在，忽略时间过滤
        console.warn('created_at 字段不存在，忽略时间过滤');
      }
    }
    
    const { count, rows: transactions } = await PointsTransaction.findAndCountAll({
      where,
      include: [
        {
          model: User,
          as: 'relatedUser',
          attributes: ['nickname'],
          required: false
        }
      ],
      order: [['created_at', 'DESC']],
      limit: parseInt(limit),
      offset: (parseInt(page) - 1) * parseInt(limit)
    });
    
    return {
      transactions,
      pagination: {
        current: parseInt(page),
        total: Math.ceil(count / limit),
        pageSize: parseInt(limit),
        totalItems: count
      }
    };
  }
  
  // 获取积分统计
  static async getPointsStats(userId) {
    try {
      const today = new Date();
      today.setHours(0, 0, 0, 0);
      const tomorrow = new Date(today);
      tomorrow.setDate(tomorrow.getDate() + 1);
      
      // 先检查表结构，如果没有 created_at 字段则使用简化查询
      let hasCreatedAt = true;
      try {
        await PointsTransaction.findOne({
          where: { 
            userId, 
            created_at: { [Op.gte]: today }
          },
          limit: 1
        });
      } catch (error) {
        if (error.message.includes('createdAt') || error.message.includes('created_at')) {
          hasCreatedAt = false;
        }
      }
      
      const [
        totalEarned,
        totalSpent,
        todayEarned,
        todayAdWatchCount,
        currentBalance,
        transactionCount
      ] = await Promise.all([
        PointsTransaction.findOne({
          attributes: [[Sequelize.fn('SUM', Sequelize.col('amount')), 'total']],
          where: { userId, type: 'earn' },
          raw: true
        }).then(result => result?.total || 0),
        PointsTransaction.findOne({
          attributes: [[Sequelize.fn('SUM', Sequelize.fn('ABS', Sequelize.col('amount'))), 'total']],
          where: { userId, type: 'consume' },
          raw: true
        }).then(result => result?.total || 0),
        // 如果没有 created_at 字段，返回 0
        hasCreatedAt ? PointsTransaction.findOne({
          attributes: [[Sequelize.fn('SUM', Sequelize.col('amount')), 'total']],
          where: { 
            userId, 
            type: 'earn',
            created_at: { [Op.gte]: today, [Op.lt]: tomorrow }
          },
          raw: true
        }).then(result => result?.total || 0) : Promise.resolve(0),
        // 如果没有 created_at 字段，返回 0
        hasCreatedAt ? PointsTransaction.count({
          where: { 
            userId, 
            source: 'ad_watch',
            created_at: { [Op.gte]: today, [Op.lt]: tomorrow }
          }
        }).catch(() => 0) : Promise.resolve(0),
        User.findByPk(userId, { attributes: ['points'] }),
        PointsTransaction.count({ where: { userId } })
      ]);
      
      return {
        totalEarned,
        totalSpent,
        todayEarned,
        adWatchCount: todayAdWatchCount,
        currentBalance: currentBalance?.points || 0,
        transactionCount
      };
    } catch (error) {
      console.error('获取积分统计失败:', error);
      // 返回默认值
      const currentBalance = await User.findByPk(userId, { attributes: ['points'] });
      return {
        totalEarned: 0,
        totalSpent: 0,
        todayEarned: 0,
        adWatchCount: 0,
        currentBalance: currentBalance?.points || 0,
        transactionCount: 0
      };
    }
  }
}

module.exports = PointsService;